﻿namespace YidanSoft.Library.EditorUtility.WinControls
{
    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using YidanSoft.Library.EditorUtility.General;
    using YidanSoft.Library.EditorUtility.Win32;

    public class TreeViewEx : TreeView
    {
        private bool itemHasFocus = false;

        public TreeViewEx()
        {
            base.DrawMode = TreeViewDrawMode.OwnerDrawAll;
        }

        private void DoTreeCustomDrawing(ref Message m)
        {
            YidanSoft.Library.EditorUtility.Win32.NMTVCUSTOMDRAW lParam = (YidanSoft.Library.EditorUtility.Win32.NMTVCUSTOMDRAW) m.GetLParam(typeof(YidanSoft.Library.EditorUtility.Win32.NMTVCUSTOMDRAW));
            IntPtr dwItemSpec = (IntPtr) lParam.nmcd.dwItemSpec;
            Rectangle itemRect = this.GetItemRect(dwItemSpec);
            Graphics graphics = Graphics.FromHdc(lParam.nmcd.hdc);
            if (this.itemHasFocus)
            {
                using (new SolidBrush(ColorUtil.VSNetSelectionColor))
                {
                    graphics.DrawRectangle(SystemPens.Highlight, itemRect.Left, itemRect.Top, itemRect.Width - 1, itemRect.Height - 1);
                }
            }
            string itemText = this.GetItemText(dwItemSpec);
            Size size = TextUtil.GetTextSize(graphics, itemText, this.Font);
            Point point = new Point(itemRect.Left, itemRect.Top + ((itemRect.Height - size.Height) / 2));
            graphics.DrawString(itemText, this.Font, SystemBrushes.ControlText, (PointF) point);
            Marshal.StructureToPtr(lParam, m.LParam, true);
            m.Result = (IntPtr) 4L;
        }

        private unsafe Rectangle GetItemRect(IntPtr hTreeItem)
        {
            YidanSoft.Library.EditorUtility.Win32.RECT lParam = new YidanSoft.Library.EditorUtility.Win32.RECT();
            (IntPtr) &lParam = hTreeItem;
            WindowsAPI.SendMessage(base.Handle, 0x1104, 1, ref lParam);
            return new Rectangle(lParam.left, lParam.top, lParam.right - lParam.left, lParam.bottom - lParam.top);
        }

        private string GetItemText(IntPtr hTreeItem)
        {
            TVITEM lParam = new TVITEM();
            lParam.hItem = hTreeItem;
            lParam.mask = 1;
            lParam.cchTextMax = 80;
            lParam.pszText = Marshal.AllocHGlobal(80);
            WindowsAPI.SendMessage(base.Handle, 0x113e, 0, ref lParam);
            return Marshal.PtrToStringAuto(lParam.pszText);
        }

        private bool NotifyTreeCustomDraw(ref Message m)
        {
            m.Result = (IntPtr) 0L;
            YidanSoft.Library.EditorUtility.Win32.NMTVCUSTOMDRAW lParam = (YidanSoft.Library.EditorUtility.Win32.NMTVCUSTOMDRAW) m.GetLParam(typeof(YidanSoft.Library.EditorUtility.Win32.NMTVCUSTOMDRAW));
            IntPtr handle = base.Handle;
            if (lParam.nmcd.hdr.hwndFrom == base.Handle)
            {
                switch (lParam.nmcd.dwDrawStage)
                {
                    case 0x10001:
                        this.itemHasFocus = false;
                        if ((lParam.nmcd.uItemState & 0x10) != 0)
                        {
                            this.itemHasFocus = true;
                        }
                        lParam.clrText = ColorUtil.RGB(SystemColors.Window.R, SystemColors.Window.G, SystemColors.Window.B);
                        lParam.clrTextBk = ColorUtil.RGB(SystemColors.Window.R, SystemColors.Window.G, SystemColors.Window.B);
                        Marshal.StructureToPtr(lParam, m.LParam, true);
                        m.Result = (IntPtr) 0x10L;
                        break;

                    case 0x10002:
                        this.DoTreeCustomDrawing(ref m);
                        break;

                    case 1:
                        m.Result = (IntPtr) 0x20L;
                        break;
                }
            }
            return false;
        }

        protected override void WndProc(ref Message message)
        {
            base.WndProc(ref message);
            if (message.Msg == 0x204e)
            {
                YidanSoft.Library.EditorUtility.Win32.NMHDR lParam = (YidanSoft.Library.EditorUtility.Win32.NMHDR) message.GetLParam(typeof(YidanSoft.Library.EditorUtility.Win32.NMHDR));
                if (lParam.code == -12)
                {
                    this.NotifyTreeCustomDraw(ref message);
                }
            }
        }
    }
}

